package org.aplikator.server.descriptor;

import org.aplikator.client.shared.descriptor.PanelDTO;
import org.aplikator.client.shared.descriptor.WidgetDTO;
import org.aplikator.server.Context;

import java.util.ArrayList;
import java.util.List;

public class Panel extends WidgetDescriptorBase {

    private List<Widget> children = new ArrayList<Widget>();
    private boolean frame = false;
    private boolean horizontal = false;

    public Panel(boolean horizontal) {
        this.horizontal = horizontal;
        setSize(12);
    }


    @Override
    public WidgetDTO getWidgetDescriptor(Context ctx) {
        PanelDTO desc = new PanelDTO(horizontal);
        desc.setFrame(frame);
        desc.setSize(getSize());
        desc.setEnabled(isEnabled());
        adjustChildrenSizes();
        for (Widget child : children) {
            desc.addChild(child.getWidgetDescriptor(ctx));
        }
        return desc;
    }

    private void adjustChildrenSizes(){
        if ( horizontal) {
            List<Widget> unsized = new ArrayList<Widget>();
            int remainingSize = 12;
            for (Widget child : children){
                if (child.getSize()>0){
                    remainingSize -= child.getSize();
                }  else{
                    unsized.add(child);
                }
            }
            if (remainingSize<unsized.size()){
                throw new IllegalStateException("Too many unsized widgets: "+unsized.size()+ "(maximum:"+remainingSize+"), widget:"+this.toString());
            } else {
                if (unsized.size()==0 || remainingSize == 0)return;
                int splitSize = remainingSize / unsized.size();
                for (Widget unsizedChild: unsized){
                    unsizedChild.setSize(splitSize);
                }
            }
        } else{
            for (Widget child : children){
                if (child.getSize()== 0){
                    child.setSize(12);
                }
            }
        }
    }

    public static Panel row(){
        return new Panel(true);
    }

    public static Panel column(){
        return new Panel(false);
    }

    public static Panel row(Object... children){
        Panel retval = row();
        return retval.add(children);
    }

    public static Panel column(Object... children){
        Panel retval = column();
        return retval.add(children);
    }


    public Panel add(Widget child) {
        if (child != null){
            if (horizontal && !(child instanceof Panel)){
                Panel subpanel = column();
                subpanel.setSize(child.getSize());
                child.setSize(12);
                subpanel.add(child);
                children.add(subpanel);
            } else {
                children.add(child);
            }
        }
        return this;
    }

    public Panel add(Property<?> property ){
        return add(property.widget());
    }

    private Panel add(Object... children){
        for (Object o : children){
            if (o instanceof Widget){
                add((Widget)o);
            }else if (o instanceof Property){
                add((Property<?>)o);
            }
        }
        return this;
    }

    public void registerProperties(Form form) {
        for (Widget child : children) {
            child.registerProperties(form);
        }
    }

    public boolean isFrame() {
        return frame;
    }

    public Panel setFrame(boolean frame) {
        this.frame = frame;
        return this;
    }

    @Override
    public Widget cloneWithReference(Reference<? extends Entity> referencingProperty){
        Panel retval;
        try {
            retval = (Panel) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new UnsupportedOperationException(e);
        }
        retval.children = new ArrayList<Widget>(children.size());
        for (Widget child: children){
            retval.children.add(child.cloneWithReference(referencingProperty));
        }
        return retval;
    }

    @Override
    public String toString() {
        return "Panel{" + "children=" + children + ", frame=" + frame + ", horizontal=" + horizontal + '}';
    }

    
}